/*
 * bsp_aes_ccm.c
 *
 *  Created on: 2023年7月5日
 *      Author: fjx
 */
#include "bsp_aes_ccm.h"
#include "string.h"
#include "app_log.h"



//static uint8_t app_key_buf[] = {
//    0xea, 0x4f, 0x6f, 0x3c, 0x2f, 0xed, 0x2b, 0x9d, 0xd9, 0x70, 0x8c, 0x2e, 0x72, 0x1a, 0xe0, 0x0f
//};


static psa_key_id_t key_id;
static psa_key_attributes_t key_attr;


static psa_algorithm_t ds_alg;
static uint8_t aes_ccm_key_count = 0;

static psa_key_id_t dynamic_key_id=0;


DS_AES_CCM_STATUS DS_aes_ccm_import_key_get_keyid (const uint8_t *key, size_t key_len ,psa_key_id_t * id)
{
  DS_AES_CCM_STATUS ret = DS_AES_CCM_STATUS_SUCCESS;
  //128 (16-byte)
  //192 (24-byte)
  //256 (32-byte)
  if(key_len != 16 && key_len != 24 && key_len != 32){
      //error
      DS_app_log_debug("The AES CCM key supports only 16, 24, and 32 bytes\n");
      return DS_AES_CCM_STATUS_ERROR_NOT_SUPPORTED;
  }
  ret = psa_import_key(&key_attr, key, key_len, id);
  if(ret != 0) {
      DS_app_log_debug("===Create key id fail,ret=[%d]=== \n",ret);
      ret = DS_AES_CCM_STATUS_KEY_FULL;
  }
  return ret;
}

psa_key_id_t DS_aes_ccm_get_dynamic_key_id (void)
{
  return dynamic_key_id;
}
uint8_t DS_aes_ccm_dynamic_init(const uint8_t *key,size_t key_len)
{
  DS_AES_CCM_STATUS ret;
  ret = DS_AES_CCM_STATUS_SUCCESS;

  if(DS_aes_ccm_get_dynamic_key_id() == DYNAMIC_AES_CCM_KEY_ID
     || DS_aes_ccm_get_dynamic_key_id() != 0 ){
      psa_destroy_key(dynamic_key_id);
  }

  psa_crypto_init();
  ds_alg = DS_aes_ccm_set_tag(CCM_TAG_LEN_4);
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, ds_alg);
  ret = DS_aes_ccm_import_key_get_keyid(key,key_len,&dynamic_key_id);

  return ret;
}


uint8_t DS_aes_ccm_get_use_key_count (void)
{
  return aes_ccm_key_count;
}
psa_key_id_t DS_aes_ccm_get_key_id (void)
{
  return key_id;
}
void DS_aes_ccm_destroy_keyid (uint32_t _key_id)
{
  if(aes_ccm_key_count != 0){
      aes_ccm_key_count--;
  }
  psa_destroy_key(_key_id);
}
psa_algorithm_t DS_aes_ccm_set_tag (CCM_Tag_Len_t len )
{
  if(len == CCM_TAG_LEN_6){
      return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM,6);
  }else if(len == CCM_TAG_LEN_8){
      return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM,8);
  }else if(len == CCM_TAG_LEN_10){
      return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM,10);
  }else if(len == CCM_TAG_LEN_12){
      return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM,12);
  }else if(len == CCM_TAG_LEN_14){
      return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM,14);
  }else if(len == CCM_TAG_LEN_16){
      return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM,16);
  }else{
      if(len != CCM_TAG_LEN_4){
          //error
          DS_app_log_debug("The AES CCM tag supports only 4, 6, 8, 10, 12, 14 and 16 bytes.\n");
      }
      return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM,4);
  }
}

DS_AES_CCM_STATUS DS_aes_ccm_import_key (const uint8_t *key, size_t key_len )
{
  DS_AES_CCM_STATUS ret = DS_AES_CCM_STATUS_SUCCESS;
  //128 (16-byte)
  //192 (24-byte)
  //256 (32-byte)
  if(key_len != 16 && key_len != 24 && key_len != 32){
      //error
      DS_app_log_debug("The AES CCM key supports only 16, 24, and 32 bytes\n");
      return DS_AES_CCM_STATUS_ERROR_NOT_SUPPORTED;
  }
  ret = psa_import_key(&key_attr, key, key_len, &key_id);
  if(ret != 0) {
      DS_app_log_debug("===Create key id fail,ret=[%d]=== \n",ret);
      ret = DS_AES_CCM_STATUS_KEY_FULL;
  }
  return ret;
}
/*
 *
 *return =DS_AES_CCM_STATUS_SUCCESS
 */
DS_AES_CCM_STATUS DS_aes_ccm_init (uint8_t *key, size_t key_len )
{
  DS_AES_CCM_STATUS ret;
  ret = DS_AES_CCM_STATUS_SUCCESS;
  if(aes_ccm_key_count >= SL_PSA_KEY_USER_SLOT_COUNT-1){
      aes_ccm_key_count++;
      return DS_AES_CCM_STATUS_KEY_FULL;
  }
  psa_crypto_init();
  ds_alg = DS_aes_ccm_set_tag(CCM_TAG_LEN_4);
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, ds_alg);
  ret = DS_aes_ccm_import_key(key,key_len);//sizeof(app_key_buf));
  DS_app_log_info("key id = 0x%lx\n",key_id);
  return ret;

}
/*
 *
 */
void DS_aes_ccm_config (void)
{

}

DS_AES_CCM_STATUS DS_aes_ccm_ae(const uint8_t *nonce,
                           size_t nonce_length,
                           const uint8_t *additional_data,
                           size_t additional_data_length,
                           const uint8_t *plaintext,
                           size_t plaintext_length,
                           uint8_t *ciphertext,
                           size_t ciphertext_size,
                           size_t *ciphertext_length )
{
  DS_AES_CCM_STATUS ret = DS_AES_CCM_STATUS_SUCCESS;
  /*
   * nonce 7~13
   */
  if(nonce_length < 7 || nonce_length > 13){
      //error
      DS_app_log_debug("The AES CCM nonce length supports only 7~13 bytes\n");
      return DS_AES_CCM_STATUS_ERROR_NOT_SUPPORTED;
  }

  if( psa_aead_encrypt(key_id, ds_alg,
                         nonce, nonce_length,
                         additional_data, additional_data_length,
                         plaintext, plaintext_length,
                         ciphertext, ciphertext_size,
                         ciphertext_length) != DS_AES_CCM_STATUS_SUCCESS) {
      ret = DS_AES_CCM_STATUS_FAIL;
  }
  return ret;
}

DS_AES_CCM_STATUS DS_aes_ccm_de(const uint8_t *nonce,
                           size_t nonce_length,
                           const uint8_t *additional_data,
                           size_t additional_data_length,
                           uint8_t *ciphertext,
                           size_t ciphertext_size,
                           uint8_t *plaintext,
                           size_t plaintext_length,
                           size_t *ciphertext_length )
{
  DS_AES_CCM_STATUS ret = DS_AES_CCM_STATUS_SUCCESS;

  /*
   * nonce 7~13
   */
  if(nonce_length < 7 || nonce_length > 13){
      //error
      DS_app_log_debug("The AES CCM nonce length supports only 7~13 bytes\n");
      return DS_AES_CCM_STATUS_ERROR_NOT_SUPPORTED;
  }

  if( psa_aead_decrypt(key_id, ds_alg,
                          nonce, nonce_length,
                          additional_data, additional_data_length,
                          ciphertext, ciphertext_size,
                          plaintext,plaintext_length,
                          ciphertext_length) != DS_AES_CCM_STATUS_SUCCESS) {
      ret = DS_AES_CCM_STATUS_FAIL;
  }

  return ret;
}
DS_AES_CCM_STATUS DS_aes_ccm_use_keyid_ae(psa_key_id_t keyid,
                           const uint8_t *nonce,
                           size_t nonce_length,
                           const uint8_t *additional_data,
                           size_t additional_data_length,
                           const uint8_t *plaintext,
                           size_t plaintext_length,
                           uint8_t *ciphertext,
                           size_t ciphertext_size,
                           size_t *ciphertext_length )
{
  DS_AES_CCM_STATUS ret = DS_AES_CCM_STATUS_SUCCESS;
  /*
   * nonce 7~13
   */
  if(nonce_length < 7 || nonce_length > 13){
      //error
      DS_app_log_debug("The AES CCM nonce length supports only 7~13 bytes\n");
      return DS_AES_CCM_STATUS_ERROR_NOT_SUPPORTED;
  }

  if( psa_aead_encrypt(keyid, ds_alg,
                         nonce, nonce_length,
                         additional_data, additional_data_length,
                         plaintext, plaintext_length,
                         ciphertext, ciphertext_size,
                         ciphertext_length) != DS_AES_CCM_STATUS_SUCCESS) {
      ret = DS_AES_CCM_STATUS_FAIL;
  }
  return ret;
}

DS_AES_CCM_STATUS DS_aes_ccm_use_keyid_de(psa_key_id_t keyid,
                           const uint8_t *nonce,
                           size_t nonce_length,
                           const uint8_t *additional_data,
                           size_t additional_data_length,
                           uint8_t *ciphertext,
                           size_t ciphertext_size,
                           uint8_t *plaintext,
                           size_t plaintext_length,
                           size_t *ciphertext_length )
{
  DS_AES_CCM_STATUS ret = DS_AES_CCM_STATUS_SUCCESS;

  /*
   * nonce 7~13
   */
  if(nonce_length < 7 || nonce_length > 13){
      //error
      DS_app_log_debug("The AES CCM nonce length supports only 7~13 bytes\n");
      return DS_AES_CCM_STATUS_ERROR_NOT_SUPPORTED;
  }

  if( psa_aead_decrypt(keyid, ds_alg,
                          nonce, nonce_length,
                          additional_data, additional_data_length,
                          ciphertext, ciphertext_size,
                          plaintext,plaintext_length,
                          ciphertext_length) != DS_AES_CCM_STATUS_SUCCESS) {
      ret = DS_AES_CCM_STATUS_FAIL;
  }

  return ret;
}
//psa_status_t DS_aese_ccm_get_key(void)
//{
////  psa_status_t ret;
////  uint8_t export_key_buf[32];
////  uint8_t export_key_len = 0;
////
////  ret = psa_export_key(DS_aes_ccm_get_key_id(),
////                        export_key_buf,
////                        sizeof(export_key_buf),
////                        &export_key_len);
////
////
////  return ret;
//}

